package com.towker.core.db;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.towker.core.mybatis.BaseMyBatisDao;
import com.towker.core.page.*;
import com.towker.core.util.BeanUtils;

/**
 * @author zyg
 * @version 1.0
 */
@SuppressWarnings("unchecked")
public abstract class BaseDao<E, PK extends Serializable> extends BaseMyBatisDao implements EntityDao<E, PK>
{
	public abstract Class getEntityClass();

	/**
	 * 根据主键取得对象
	 */
	public Object getById(PK primaryKey)
	{
		Object object = getSqlSessionTemplate().selectOne(getFindByPrimaryKeyStatement(), primaryKey);
		return object;
	}
	
	/**
	 * 根据别名取得对象
	 */
	public Object getByAlias(String account){
		
		Object object = getSqlSessionTemplate().selectOne(getFindByPrimaryKeyStatement(), account);
		return object;
	}

	/**
	 * 删除主键ID
	 */
	public int delById(PK id)
	{
		int affectCount = getSqlSessionTemplate().delete(getDeleteStatement(), id);
		return affectCount;
	}

	/**
	 * 保存对象
	 */
	public void add(E entity)
	{
		prepareObjectForSaveOrUpdate(entity);
		getSqlSessionTemplate().insert(getInsertStatement(), entity);
	}
	
	/**
	 * 更新对象
	 */
	public int update(E entity)
	{
		prepareObjectForSaveOrUpdate(entity);
		int affectCount = getSqlSessionTemplate().update(getUpdateStatement(), entity);
		return affectCount;
	}

	/**
	 * 用于子类覆盖,在insert,update之前调用
	 * @param o
	 */
	protected void prepareObjectForSaveOrUpdate(E o)
	{
	}

	public String getIbatisMapperNamespace()
	{
		// throw new RuntimeException("not yet implement");
		return getEntityClass().getName();
	}
	
	public static void main(String[] args)
	{
		System.out.println(BaseDao.class.getName()) ;
	}

	public String getFindByPrimaryKeyStatement()
	{
		return getIbatisMapperNamespace() + ".getById";
	}

	public String getInsertStatement()
	{
		String namespace = getIbatisMapperNamespace();
		return namespace + ".add";
	}

	public String getUpdateStatement()
	{
		return getIbatisMapperNamespace() + ".update";
	}

	public String getDeleteStatement()
	{
		return getIbatisMapperNamespace() + ".delById";
	}

	/**
	 * 取得数据条数
	 * @param pageRequest
	 * @return
	 */
	public int getCount(PageRequest pageRequest)
	{
		return getCount(getIbatisMapperNamespace() + ".getAllCount", pageRequest);
	}

	/**
	 * 取得数据条数
	 * @param pageRequest
	 * @return
	 */
	protected int getCount(String countStatmentName, PageRequest pageRequest)
	{
		Integer totalCount = (Integer) this.getSqlSessionTemplate().selectOne(countStatmentName, pageRequest.getFilters());
		return totalCount.intValue();
	}

	/**
	 * 取得分页数据
	 * @param pageRequest
	 * @return
	 */
	public PageModel getPage(PageRequest pageRequest)
	{
		String statementName = getIbatisMapperNamespace() + ".getAll";
		return getPage(statementName, pageRequest);
	}

	/**
	 * 传入分页查询和对应的计数查询
	 * @param statementName
	 * @param countStatmentName
	 * @param pageRequest
	 * @return
	 */
	protected PageModel getPage(String statementName, String countStatmentName, PageRequest pageRequest)
	{
		Integer totalCount = (Integer) this.getSqlSessionTemplate().selectOne(countStatmentName, pageRequest.getFilters());
		PageModel page = new PageModel(pageRequest, totalCount.intValue());
		// 其它分页参数,用于不喜欢或是因为兼容性而不使用方言(Dialect)的分页用户使用. 与getSqlMapClientTemplate().queryForList(statementName,
		// parameterObject)配合使用
		Map filters = new HashMap();
		int i = page.getFirstResult();
		// System.out.println("i:" + i);
		filters.put("offset", i);
		filters.put("pageSize", page.getPageSize());
		// filters.put("lastRows", page.getFirstResult() + page.getPageSize());
		filters.put("sortColumns", pageRequest.getSortColumns());
		// 混合两个filters为一个filters,MapAndObject.get()方法将在两个对象取值,Map如果取值为null,则再在Bean中取值

		if (pageRequest.getFilters() instanceof Map)
		{
			filters.putAll((Map) pageRequest.getFilters());
		}
		else
		{
			Map parameterObject = BeanUtils.describe(pageRequest.getFilters());
			filters.putAll(parameterObject);
		}
		List list = getSqlSessionTemplate().selectList(statementName, filters, page.getFirstResult(), page.getPageSize());
		page.setResult(list);
		return page;
	}

	protected PageModel getPage(String statementName, PageRequest pageRequest)
	{
		String countStatementName=statementName + "Count";
		Integer totalCount = (Integer) this.getSqlSessionTemplate().selectOne(countStatementName, pageRequest.getFilters());
		PageModel page = new PageModel(pageRequest, totalCount.intValue());
		// 其它分页参数,用于不喜欢或是因为兼容性而不使用方言(Dialect)的分页用户使用. 与getSqlMapClientTemplate().queryForList(statementName,
		// parameterObject)配合使用
		Map filters = new HashMap();
		int i = page.getFirstResult();
		// System.out.println("i:" + i);
		filters.put("offset", i);
		filters.put("pageSize", page.getPageSize());
		// filters.put("lastRows", page.getFirstResult() + page.getPageSize());
		filters.put("sortColumns", pageRequest.getSortColumns());
		// 混合两个filters为一个filters,MapAndObject.get()方法将在两个对象取值,Map如果取值为null,则再在Bean中取值

		if (pageRequest.getFilters() instanceof Map)
		{
			filters.putAll((Map) pageRequest.getFilters());
		}
		else
		{
			Map parameterObject = BeanUtils.describe(pageRequest.getFilters());
			filters.putAll(parameterObject);
		}
		List list = getSqlSessionTemplate().selectList(statementName, filters, page.getFirstResult(), page.getPageSize());
		page.setResult(list);
		return page;
	}
	
	public List getList(PageRequest pageRequest)
	{
		String statementName = getIbatisMapperNamespace() + ".getAll";
		return getList(statementName, pageRequest);
	}

	public List getList(String statementName, PageRequest pageRequest)
	{
		Map filters = new HashMap();
		filters.put("sortColumns", pageRequest.getSortColumns());
		// 混合两个filters为一个filters,MapAndObject.get()方法将在两个对象取值,Map如果取值为null,则再在Bean中取值
		if (pageRequest.getFilters() instanceof Map)
		{
			filters.putAll((Map) pageRequest.getFilters());
		}
		else
		{
			Map parameterObject = BeanUtils.describe(pageRequest.getFilters());
			filters.putAll(parameterObject);
		}
		List list = getSqlSessionTemplate().selectList(statementName, filters);
		return list;
	}

	public List getAll()
	{
		throw new UnsupportedOperationException();
	}

	public boolean isUnique(E entity, String uniquePropertyNames)
	{
		throw new UnsupportedOperationException();
	}

	public void flush()
	{
		// ignore
	}
}
